package com.wq.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wq.BusinessException;
import com.wq.dto.UserDTO;
import com.wq.dto.UserLoginDTO;
import com.wq.entity.User;
import com.wq.enums.RespEnum;
import com.wq.mapper.UserMapper;
import com.wq.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wq.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wq
 * @since 2025-11-09
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private RedisTemplate<String, String> redisTemplate;
    @Resource
    private JwtUtil jwtUtil;
    @Resource
    private RabbitTemplate rabbitTemplate;

    @Override
    public String login(UserLoginDTO userLoginDTO) {
        // 先验证验证码
        String key = "user:sso:login:" + userLoginDTO.getPhone() + "code";
        String codeInRedis = redisTemplate.opsForValue().get(key);
        if (codeInRedis == null) {
            throw new BusinessException(RespEnum.CODE_EXPIRED);
        }
        if (!codeInRedis.equals(userLoginDTO.getCode())) {
            throw new BusinessException(RespEnum.CODE_ERROR);
        }

        // 条件构造器，用来构建查询条件
        LambdaQueryWrapper<User> Wrapper = new LambdaQueryWrapper<>();
        // 设置查询条件，要求数据库里的username与前端传进来的username相等
        Wrapper.eq(User::getPhone, userLoginDTO.getPhone());
        // 调用getOne()方法，根据条件构造器查询数据库，返回User对象
        User user = this.getOne(Wrapper);

        // 如果没有对应的user对象，则抛出异常
        if (user == null) {
            throw new BusinessException(RespEnum.USER_APPLY_NOT_EXISTS);
        }

        // 检查账号状态
        if (user.getStatus() == 0) {
            throw new BusinessException(RespEnum.ERROR_STATUS);
        }

        // Jwts.claims()：创建一个新的 Claims 对象，该对象可以用来设置JWT中的声明信息。
        Claims claims = Jwts.claims();
        // 将user的id存放在claims中
        // 角色类型：1-普通员工，2-部门经理，3-系统管理员
        claims.put("id", user.getId());
        claims.put("roleType", user.getRoleType());
        String token = jwtUtil.createToken(claims);

        // 登录成功后清除验证码
        redisTemplate.delete(key);

        return token;
    }

    @Override
    public void sendCode(String phone) {
        // 判断手机号合法
        if (phone.length() != 11) {
            throw new BusinessException(RespEnum.INVALID_PHONE);
        }

        String countKey = "user:sso:login:" + phone + "count";

        // 使用原子操作检查发送次数
        Long currentCount = redisTemplate.opsForValue().increment(countKey, 1);
        if (currentCount == 1) {
            // 第一次设置过期时间
            redisTemplate.expire(countKey, 5, TimeUnit.MINUTES);
        } else if (currentCount > 5) {
            // 超过限制次数，回退计数并抛出异常
            redisTemplate.opsForValue().decrement(countKey, 1);
            throw new BusinessException(RespEnum.TOO_MANY_REQUESTS);
        }

        // 生成验证码
        Random random = new Random();
        String code = random.nextInt(8888) + 1000 + "";
        String codeKey = "user:sso:login:" + phone + "code";

        // 存储验证码
        redisTemplate.opsForValue().set(codeKey, code, 360, TimeUnit.SECONDS);

        // 往MQ中发送短信
        rabbitTemplate.convertAndSend("test.direct", "sms", "您的登录短信验证码：" + code);
        log.info("验证码是：{}", code);
    }

    @Override
    public Page<User> getUserList(Integer pageNum, Integer pageSize, String keyword) {
        Page<User> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        
        if (keyword != null && !keyword.trim().isEmpty()) {
            wrapper.like(User::getRealName, keyword)
                    .or()
                    .like(User::getPhone, keyword)
                    .or()
                    .like(User::getEmail, keyword);
        }
        
        wrapper.orderByDesc(User::getCreateTime);
        return this.page(page, wrapper);
    }

    @Override
    public User addUser(UserDTO userDTO) {
        // 检查手机号是否已存在
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone, userDTO.getPhone());
        User existUser = this.getOne(wrapper);
        
        if (existUser != null) {
            throw new BusinessException(RespEnum.INVALID_PARAMETERS);
        }
        
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        
        // 设置默认密码（手机号后6位）
        user.setPassword(userDTO.getPhone().substring(5));
        
        this.save(user);
        return user;
    }

    @Override
    public Boolean updateUser(Integer id, UserDTO userDTO) {
        User user = this.getById(id);
        if (user == null) {
            throw new BusinessException(RespEnum.INVALID_PARAMETERS);
        }
        
        // 检查手机号是否被其他用户使用
        if (userDTO.getPhone() != null && !userDTO.getPhone().equals(user.getPhone())) {
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(User::getPhone, userDTO.getPhone())
                    .ne(User::getId, id);
            User existUser = this.getOne(wrapper);
            
            if (existUser != null) {
                throw new BusinessException(RespEnum.INVALID_PARAMETERS);
            }
        }
        
        BeanUtils.copyProperties(userDTO, user);
        user.setId(id);
        return this.updateById(user);
    }

    @Override
    public Boolean deleteUser(Integer id) {
        User user = this.getById(id);
        if (user == null) {
            throw new BusinessException(RespEnum.INVALID_PARAMETERS);
        }
        
        // 不允许删除系统管理员
        if (user.getRoleType() == 3) {
            throw new BusinessException(RespEnum.INVALID_PARAMETERS);
        }
        
        return this.removeById(id);
    }

    @Override
    public Boolean updateUserStatus(Integer id, Byte status) {
        User user = this.getById(id);
        if (user == null) {
            throw new BusinessException(RespEnum.INVALID_PARAMETERS);
        }
        
        // 不允许禁用系统管理员
        if (user.getRoleType() == 3 && status == 0) {
            throw new BusinessException(RespEnum.INVALID_PARAMETERS);
        }
        
        user.setStatus(status);
        return this.updateById(user);
    }



//    @Override
//    public String login(UserLoginDTO userLoginDTO) {
//        String key = "user:sso:login:" + userLoginDTO.getPhone()+"code";
//        String codeInRedis = redisTemplate.opsForValue().get(key);
//        if(codeInRedis==null){
//            throw new RuntimeException("验证码已过期");
//        }
//        if (!codeInRedis.equals(userLoginDTO.getCode())) {
//            throw new RuntimeException("验证码错误");
//        }
//        // 条件构造器，用来构建查询条件
//        LambdaQueryWrapper<User> Wrapper = new LambdaQueryWrapper<>();
//        // 设置查询条件，要求数据库里的username与前端传进来的username相等
//        Wrapper.eq(User::getPhone, userLoginDTO.getPhone());
//        // 调用getOne()方法，根据条件构造器查询数据库，返回User对象
//        User user = this.getOne(Wrapper);
//        if (user.getStatus() == 0){
//            throw new RuntimeException("账号被禁用，请联管理员");
//        }
//
//        // 如果没有对应的user对象，则抛出异常
//        // 抛出异常可以立即停止当前的执行流程
//        if (user == null){
//            throw new RuntimeException("用户名不存在或者密码不正确");
//        }
//
//        // Jwts.claims()：创建一个新的 Claims 对象，该对象可以用来设置JWT中的声明信息。
//        Claims claims = Jwts.claims();
//        // 将user的id存放在claims中
//        // 角色类型：1-普通员工，2-部门经理，3-系统管理员
//        claims.put("id",user.getId());
//        claims.put("roleType",user.getRoleType());
//        String token=jwtUtil.createToken(claims);
//
//        return token;
//    }

//    @Override
//    public void sendCode(String phone) {
//        Random random = new Random();
//        String code = random.nextInt(8888) + 1000 + "";
//
//        /*
//        todo 缓存验证码
//        redis编排方式： 项目名:模块名:场景名:特征码
//         */
//        //判断手机号合法
//        if (phone.length() != 11) {
//            throw new RuntimeException("手机号格式不正确");
//        }
//        String key = "user:sso:login:" + phone+"code";
//        String count = "user:sso:login:" + phone+"count";
//
//        //判断是否超过5次
//        if(redisTemplate.hasKey(count)){
//            String s = redisTemplate.opsForValue().get(count);
//            if (s==null){
//                throw new RuntimeException("手机号格式不正确");
//            }
//            int countInt=Integer.parseInt(s);
//            if (countInt>=5) {
//                throw new RuntimeException("请勿频繁请求验证码");
//            }
//            }
//        redisTemplate .opsForValue().set(key, code, 360, TimeUnit.SECONDS);
//        //记录短信发送次数
//        if (!redisTemplate.hasKey(count)){
//            redisTemplate .opsForValue().set(count, "1", 5, TimeUnit.MINUTES);
//        }else {
//            int countInt=Integer.parseInt(Objects.requireNonNull(redisTemplate.opsForValue().get(count)))+1;
//            redisTemplate .opsForValue().set(count, countInt+"", 5, TimeUnit.MINUTES);
//        }
//
//        //往MQ中发送短信
//        rabbitTemplate.convertAndSend("test.direct","sms","您的登录短信验证码："+code);
//        log.info("验证码是：{}", code);
//    }


}
